﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;

namespace WentStateMachine
{
    public static class FindStateHelper
    {
        static List<Item> types = new List<Item>();
        static FindStateHelper()
        {
            findAllState();
        }

        static void findAllState()
        {
            types.Clear();
            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                IEnumerable<Type> allTypes;

                try
                {
                    allTypes = assembly.GetTypes();

                }
                catch (ReflectionTypeLoadException e)
                {
                    allTypes = e.Types.Where(t => t != null);
                    Debug.LogWarning(
                        $"RpcCollectionGenerator failed loading assembly: {(assembly.IsDynamic ? assembly.ToString() : assembly.Location)}");
                }

                var pipelineTypes = allTypes.Where(t =>
                    typeof(StateBehaviour).IsAssignableFrom(t) &&
                    !t.IsAbstract && t.IsPublic &&
                    !t.ContainsGenericParameters);

                foreach (var pt in pipelineTypes)
                {
                    StateAttribute attri;
                    if ((attri = pt.GetCustomAttribute<StateAttribute>(false)) != null)
                        types.Add(new Item()
                        {
                            Name = attri.DisplayName,
                            Type = pt
                        });
                }
            }
        }

        public struct Item
        {
            public string Name;
            public Type Type;
        }

        public static Type FindTypeByName(string name)
        {
            foreach(var item in types)
            {
                if (item.Name == name)
                    return item.Type;
            }
            Debug.LogError("Can not find type named " + name);
            return null;
        }

        public static Type FindTypeByTypeName(string typeName)
        {
            foreach (var item in types)
            {
                if (item.Type.FullName == typeName)
                    return item.Type;
            }
            return null;
        }


        private static string[] _names;
        public static string[] Names
        {
            get
            {
                if(_names == null)
                {
                    string[] names = new string[types.Count];
                    for (var i = 0; i < names.Length; i++)
                    {
                        names[i] = types[i].Name;
                    }
                    _names = names;
                }
                
                return _names;
            }
        }
    }
}
